/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.store.client.components;

import java.util.ArrayList;
import java.util.List;

import com.elf.gwt.common.client.exception.TooManyItemsInCartException;
import com.elf.gwt.common.client.model.CurrencyModel;
import com.elf.gwt.common.client.model.DetailedProductModel;
import com.elf.gwt.common.client.model.ProductMetaModel;
import com.elf.gwt.common.client.model.ProductModel;
import com.elf.gwt.common.client.utils.CommonUtils;
import com.elf.gwt.store.client.StoreComponentController;
import com.elf.gwt.store.client.utils.StoreUtils;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;

/**
 *  
 */
public class ProductsComponent extends JSONServerComponent
{
	protected Grid bodyPanel;
	protected ProductMetaModel productMetaModel;
	protected List<ProductModel> productModels;
	protected ProductModel tmpProductModel;
	protected DialogBox dialogBox = null;
	protected Image dialogImage = null;

	protected int maxNumCols = 3;
	protected int numCols = 0;
	protected boolean clearManufacturerId;
	
	protected int prevNumRows = -1;
	protected int prevNumCols = -1;
	
	/**
	 * Constructor
	 */
	public ProductsComponent(StoreComponentController controller, String stylePrefix, String strRightImage, boolean linkRightImage)
	{
		super(controller, stylePrefix, strRightImage, linkRightImage);
		
		productModels = new ArrayList<ProductModel>();
	}

	protected void buildMetaModel(JSONObject jsonObject) throws Exception
	{
		productMetaModel = new ProductMetaModel(jsonObject);
	}


	/**
	 * BuildData from JSONArray
	 * @param jsonArray
	 */
	protected void buildModel(JSONArray jsonArray) throws Exception
	{
		productModels.clear();
		super.buildModel(jsonArray);
	}

	protected void buildModel(JSONObject jsonObject) throws Exception
	{
		productModels.add(new ProductModel(jsonObject, productMetaModel.getImageWidthMax(), productMetaModel.getImageHeightMax()));
	}

	public void buildFromModel() throws Exception
	{
		int sz = productModels.size();
		numCols = Math.min(getMaxNumCols(), sz);
		int numRows = (int)Math.round(Math.ceil((1.0 * sz)/(numCols * 1.0)));
		int colWidth = (int)Math.round(100.00 / numCols);

		bodyPanel = (Grid)panel.getWidget(1, 0);
		boolean reuse = true;
		if (numRows != prevNumRows || numCols != prevNumCols || bodyPanel == null)
		{
			reuse = false;
			prevNumRows = numRows;
			prevNumCols = numCols;
			bodyPanel = new Grid(numRows, numCols);
			bodyPanel.addStyleName("ComponentBodyPanel");
			bodyPanel.addStyleName(getHandle() + "BodyPanel");
			bodyPanel.addClickHandler(tableHandler); 
		}
		CellFormatter cf = bodyPanel.getCellFormatter();

		CurrencyModel currencyModel = StoreComponentController.currenciesComponent.getCurrencyModel();
		for (int i = 0; i < sz; i++)
		{
			ProductModel model = productModels.get(i);

			int row = (int)Math.round(Math.floor((1.0 * i)/(numCols * 1.0)));
			int col = i - (row * numCols);

			String priceOut = CommonUtils.productPriceDisplay(currencyModel, model.getPrice(), model.getDiscountPrice(), model.getSpecialPrice());
			if (model.getWeight() < 0.00001 && !model.isVirtual()) priceOut += "<br/><strong>Free Shipping!</strong>";
			String[] imageSize = model.getImageSize();
			
			if (!reuse)
			{
				VerticalPanel vpanel = new VerticalPanel();
				vpanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
				Image image = new Image();
				image.setUrl(StoreUtils.getImageProductsDirectory() + model.getImage());
				image.setSize(imageSize[0], imageSize[1]);
				image.setTitle(model.getName());
				vpanel.add(image);
				vpanel.add(new InlineLabel(model.getName()));
				vpanel.add(new InlineHTML(priceOut));

				bodyPanel.setWidget(row, col, vpanel);
				cf.addStyleName(row, col, "ComponentImage");
				cf.addStyleName(row, col, getHandle() + "Image");
				cf.addStyleName(row, col, "ComponentLink");
				cf.setHorizontalAlignment(row, col, HasHorizontalAlignment.ALIGN_CENTER);
				cf.setWidth(row, col, colWidth + "%");
			}
			else
			{
				VerticalPanel vpanel = (VerticalPanel)bodyPanel.getWidget(row, col);
				Image image = (Image)vpanel.getWidget(0);
				image.setUrl(StoreUtils.getImageProductsDirectory() + model.getImage());
				image.setSize(imageSize[0], imageSize[1]);
				image.setTitle(model.getName());
				InlineLabel lbl = (InlineLabel)vpanel.getWidget(1);
				lbl.setText(model.getName());
				InlineHTML html = (InlineHTML)vpanel.getWidget(2);
				html.setHTML(priceOut);
			}
		}
		if (!reuse)
		{
			panel.setWidget(1, 0, bodyPanel);
		}
		onBuilt();
	}

	protected ClickHandler tableHandler= new ClickHandler() {
		public void onClick(ClickEvent event)
		{
			HTMLTable.Cell cell = bodyPanel.getCellForEvent(event);
			int rowIndex = cell.getRowIndex();
			int cellIndex = cell.getCellIndex();
			int index = (rowIndex * numCols) + cellIndex;
			ProductModel productModel = getProductModel(index);
			int mid = 0;
			if (!isClearManufacturerId()) mid = StoreComponentController.manufacturersComponent.getManufacturerModel().getId();
			onSelection("ProductComponent--" + productModel.getId() + "--"
					+ productModel.getCategoryId() + "--" 
					+ mid);
		}
	};

	protected void onCartSelection(int index)
	{
		ProductModel productModel = getProductModel(index);
		if (productModel.isHasAttributes() || productModel.getPrice() != productModel.getDiscountPrice())
		{
			int mid = 0;
			if (!clearManufacturerId) mid = StoreComponentController.manufacturersComponent.getManufacturerModel().getId();
			onSelection("ProductComponent--" + productModel.getId() + "--"
					+ productModel.getCategoryId() + "--" 
					+ mid);
		}
		else
		{
			DetailedProductModel cartProductModel = new DetailedProductModel(0, 0, "");
			cartProductModel.update(productModel);
			cartProductModel.setCartQuantity(1);
			cartProductModel.setCartQuantityMax(productMetaModel.getCartQuantityMax());
			try {
				StoreComponentController.cartComponent.getCartModel().addProduct(cartProductModel);
			}
			catch(TooManyItemsInCartException e) {
				Window.alert(storeController.getStoreConstants().CartComponentTooManyItems());
			}

			if (productMetaModel.isDisplayCart())
			{
				onSelection("CartComponent");
			}
		}
	}

	public ProductModel getProductModel(int i) {
		return productModels.get(i);
	}

	public int getMaxNumCols() {
		int clientNumCols = maxNumCols;
		if (Window.getClientWidth() < 801 && maxNumCols > 1) clientNumCols = 1;
		else if (Window.getClientWidth() < 1201 && maxNumCols > 2) clientNumCols = 2;
		return clientNumCols;
	}

	public void setMaxNumCols(int maxNumCols) {
		this.maxNumCols = maxNumCols;
	}

	public boolean isClearManufacturerId() {
		return clearManufacturerId;
	}

	public void setClearManufacturerId(boolean clearManufacturerId) {
		this.clearManufacturerId = clearManufacturerId;
	}

	protected MouseOverHandler mouseOverHandler = new MouseOverHandler() {
		public void onMouseOver(MouseOverEvent event)
		{
			Widget source = (Widget)event.getSource();
			String stylenames = source.getStyleName();
			int loc = stylenames.indexOf("index:");
			stylenames = stylenames.substring(loc+6);
			loc = stylenames.indexOf(" ");
			if (loc > -1) stylenames = stylenames.substring(0, loc);
			int id = Integer.parseInt(stylenames);
			ProductModel model = productModels.get(id);
			String imagename = model.getImage();
			if (dialogBox == null) {
				dialogBox = new DialogBox();
				dialogBox.setStyleName(getHandle() + "DialogBox");
				dialogBox.setModal(false);
				dialogImage = new Image();
				dialogBox.add(dialogImage);
			}
			dialogImage.setUrl(StoreUtils.getImageProductsDirectory() + imagename);
			String[] imageSize = model.getImageSize();
			int width = Integer.parseInt(imageSize[0]) * 2;
			int height = Integer.parseInt(imageSize[1]) * 2;
			dialogImage.setSize(String.valueOf(width), String.valueOf(height));
			dialogBox.center();
			dialogBox.show();
		}
	};

	protected MouseOutHandler mouseOutHandler = new MouseOutHandler() {
		public void onMouseOut(MouseOutEvent event)
		{
			if (dialogBox != null  && dialogBox.isShowing()) dialogBox.hide();
		}
	};
}
